import * as THREE from "three";

const SPEED = 0.0008;
const NUMS = 6;
export default class RailCar {
  constructor() {
    this.models = [];
    this.cars = [];
    this.main = new THREE.Object3D();
    this.path = new THREE.CurvePath();
    this.progress = 1;
  }

  add(object) {
    this.models.push(object);
  }

  addPathLine(geometry) {
    const position = geometry.attributes.position.array;
    const nums = position.length / 3;
    const points = [];
    for (let i = 0; i < nums; i++) {
      points.push(new THREE.Vector3(position[i * 3], position[i * 3 + 1], position[i * 3 + 2]));
    }
    for (let i = 0; i < nums - 1; i++) {
      const line = new THREE.LineCurve3(points[i], points[i + 1]);
      this.path.add(line);
    }
    const lastLine = new THREE.LineCurve3(points[nums - 1], points[0]);
    this.path.add(lastLine);
  }

  build() {
    const car = new THREE.Object3D();
    const defaultPosition = this.models[0].position.clone();
    this.models.map(item => {
      item.position.set(0, 0, 0);
      car.add(item);
    });
    car.position.copy(defaultPosition);
    this.main.add(car);
    this.cars.push(car);

    for (let i = 1; i < NUMS; i++) {
      const nCar = car.clone();
      this.cars.push(nCar);
      this.main.add(nCar);
    }
  }

  update() {
    this.progress -= SPEED;
    if (this.progress < 0) {
      this.progress = 1;
    }
    for (let i = 0; i < this.cars.length; i++) {
      const car = this.cars[i];
      let progress = this.progress - i * SPEED * 20;
      if (progress < 0) {
        progress = 1 + this.progress - i * SPEED * 20;
      }
      const currentPoint = this.path.getPoint(progress);
      const tangent = this.path.getTangent(progress);
      tangent.negate();

      const randY = new THREE.Vector3(0, 0, 1).angleTo(tangent);
      const axis = new THREE.Vector3(0, 1, 0);

      axis.applyAxisAngle(new THREE.Vector3(0, 0, 1), car.rotation.z);
      car.setRotationFromAxisAngle(axis, randY - Math.PI / 2);

      const tangentZ = tangent.clone();
      tangentZ.z = 0;
      const randZ = new THREE.Vector3(1, 0, 0).angleTo(tangentZ);

      if (new THREE.Vector3(1, 0, 0).cross(tangent).z > 0) {
        car.rotation.z = randZ;
      } else {
        car.rotation.z = -randZ;
      }

      car.position.copy(currentPoint);
    }
  }
}